<template>
  <teleport to="body">
   <div class="ant-modal-root">
     <div class="ant-modal-mask"></div>
     <div class="ant-modal-wrap">
       <div ref="dragRef" class="ant-modal" id="drag">
         <div ref="titleRef" class="title">
           <h2>这是一个可以拖动的窗口</h2>
           <div>
             <a ref="minRef" class="min" title="最小化"></a>
             <a ref="maxRef" class="max" title="最大化"></a>
             <a ref="revertRef" class="revert" title="还原"></a>
             <a ref="closeRef" class="close" title="关闭"></a>
           </div>
         </div>
         <div ref="resizeLRef" class="resizeL"></div>
         <div ref="resizeTRef" class="resizeT"></div>
         <div ref="resizeRRef" class="resizeR"></div>
         <div ref="resizeBRef" class="resizeB"></div>
         <div ref="resizeLTRef" class="resizeLT"></div>
         <div ref="resizeTRRef" class="resizeTR"></div>
         <div ref="resizeBRRef" class="resizeBR"></div>
         <div ref="resizeLBRef" class="resizeLB"></div>
         <div ref="content" class="content">
           ① 窗口可以拖动；<br/>
           ② 窗口可以通过八个方向改变大小；<br/>
           ③ 窗口可以最小化、最大化、还原、关闭；<br/>
           ④ 限制窗口最小宽度/高度。
         </div>
       </div>
     </div>
   </div>
  </teleport>
</template>

<script lang="ts">
import {defineComponent, onMounted, ref} from 'vue'

export default defineComponent({
  name: "basic-modal",
  setup() {
    const dragRef = ref<any>(null)
    const titleRef = ref<any>(null)
    const resizeLRef = ref<any>(null)
    const resizeTRef = ref<any>(null)
    const resizeRRef = ref<any>(null)
    const resizeBRef = ref<any>(null)
    const resizeLTRef = ref<any>(null)
    const resizeTRRef = ref<any>(null)
    const resizeBRRef = ref<any>(null)
    const resizeLBRef = ref<any>(null)
    const minRef = ref<any>(null)
    const maxRef = ref<any>(null)
    const revertRef = ref<any>(null)
    const closeRef = ref<any>(null)

    const dragMinWidth = 250
    const dragMinHeight = 124

    function drag(oDrag, handle)
    {
      let disX = 0
      const dixY = 0
      handle = handle || oDrag
      handle.style.cursor = "move"
      handle.onmousedown = function (event)
      {
        event = event || window.event
        disX = event.clientX - oDrag.offsetLeft
        const disY = event.clientY - oDrag.offsetTop

        document.onmousemove = function (event)
        {
          event = event || window.event
          let iL = event.clientX - disX
          let iT = event.clientY - disY
          const maxL = document.documentElement.clientWidth - oDrag.offsetWidth
          const maxT = document.documentElement.clientHeight - oDrag.offsetHeight

          iL <= 0 && (iL = 0)
          iT <= 0 && (iT = 0)
          iL >= maxL && (iL = maxL)
          iT >= maxT && (iT = maxT)

          oDrag.style.left = iL + "px"
          oDrag.style.top = iT + "px"

          return false
        }

        document.onmouseup = function ()
        {
          document.onmousemove = null
          document.onmouseup = null
        }
        return false
      }
      //最大化按钮
      maxRef.value.onclick = function ()
      {
        oDrag.style.top = oDrag.style.left = 0
        oDrag.style.width = document.documentElement.clientWidth - 2 + "px"
        oDrag.style.height = document.documentElement.clientHeight - 2 + "px"
        this.style.display = "none"
        revertRef.value.style.display = "block"
      }
      //还原按钮
      revertRef.value.onclick = function ()
      {
        oDrag.style.width = dragMinWidth + "px"
        oDrag.style.height = dragMinHeight + "px"
        oDrag.style.left = (document.documentElement.clientWidth - oDrag.offsetWidth) / 2 + "px"
        oDrag.style.top = (document.documentElement.clientHeight - oDrag.offsetHeight) / 2 + "px"
        this.style.display = "none"
        maxRef.value.style.display = "block"
      }
      //最小化按钮
      minRef.value.onclick = closeRef.value.onclick = function ()
      {
        oDrag.style.display = "none"
        const oA = document.createElement("a")
        oA.className = "open"
        oA.href = "javascript:;"
        oA.title = "还原"
        document.body.appendChild(oA)
        oA.onclick = function ()
        {
          oDrag.style.display = "block"
          document.body.removeChild(oDrag)
          this.onclick = null
        }
      }
      //阻止冒泡
      minRef.value.onmousedown = maxRef.value.onmousedown = closeRef.value.onmousedown = function (event)
      {
        this.onfocus = function () {this.blur()};
        (event || window.event).cancelBubble = true
      }
    }

    function resize(oParent, handle, isLeft, isTop, lockX, lockY)
    {
      handle.onmousedown = function (event)
      {
        event = event || window.event
        const disX = event.clientX - handle.offsetLeft
        const disY = event.clientY - handle.offsetTop
        const iParentTop = oParent.offsetTop
        const iParentLeft = oParent.offsetLeft
        const iParentWidth = oParent.offsetWidth
        const iParentHeight = oParent.offsetHeight

        document.onmousemove = function (event)
        {
          event = event || window.event

          const iL = event.clientX - disX
          const iT = event.clientY - disY
          const maxW = document.documentElement.clientWidth - oParent.offsetLeft - 2
          const maxH = document.documentElement.clientHeight - oParent.offsetTop - 2
          let iW = isLeft ? iParentWidth - iL : handle.offsetWidth + iL
          let iH = isTop ? iParentHeight - iT : handle.offsetHeight + iT

          isLeft && (oParent.style.left = iParentLeft + iL + "px")
          isTop && (oParent.style.top = iParentTop + iT + "px")

          iW < dragMinWidth && (iW = dragMinWidth)
          iW > maxW && (iW = maxW)
          lockX || (oParent.style.width = iW + "px")

          iH < dragMinHeight && (iH = dragMinHeight)
          iH > maxH && (iH = maxH)
          lockY || (oParent.style.height = iH + "px")

          if((isLeft && iW == dragMinWidth) || (isTop && iH == dragMinHeight)) document.onmousemove = null

          return false
        }
        document.onmouseup = function ()
        {
          document.onmousemove = null
          document.onmouseup = null
        }
        return false
      }
    }

    const initWin = () => {

      drag(dragRef.value, titleRef.value)
      //四角
      resize(dragRef.value, resizeLTRef.value, true, true, false, false)
      resize(dragRef.value, resizeTRRef.value, false, true, false, false)
      resize(dragRef.value, resizeBRRef.value, false, false, false, false)
      resize(dragRef.value, resizeLBRef.value, true, false, false, false)
      //四边
      resize(dragRef.value, resizeLRef.value, true, false, false, true)
      resize(dragRef.value, resizeTRef.value, false, true, true, false)
      resize(dragRef.value, resizeRRef.value, false, false, false, true)
      resize(dragRef.value, resizeBRef.value, false, false, true, false)

      dragRef.value.style.left = (document.documentElement.clientWidth - dragRef.value.offsetWidth) / 2 + "px"
      dragRef.value.style.top = (document.documentElement.clientHeight - dragRef.value.offsetHeight) / 2 + "px"
    }

    onMounted(() => {
      initWin()
      window.onresize = initWin
    })

    return {
      dragRef,
      titleRef,
      resizeLRef,
      resizeTRef,
      resizeRRef,
      resizeBRef,
      resizeLTRef,
      resizeTRRef,
      resizeBRRef,
      resizeLBRef,
      minRef,
      maxRef,
      revertRef,
      closeRef
    }
  }
})
</script>

<style scoped>
body, div, h2 {
  margin: 0;
  padding: 0;
}

body {
  background: url(https://www.17sucai.com/preview/65612/2014-02-17/Desktop1/img/bg.jpg);
  font: 12px/1.5 \5fae\8f6f\96c5\9ed1;
  color: #333;
}

/* drag */
#drag {
  position: absolute;
  top: 100px;
  left: 100px;
  width: 300px;
  height: 160px;
  background: #e9e9e9;
  border: 1px solid #444;
  border-radius: 5px;
  box-shadow: 0 1px 3px 2px #666;
}

#drag .title {
  position: relative;
  height: 27px;
  margin: 5px;
}

#drag .title h2 {
  font-size: 14px;
  height: 27px;
  line-height: 24px;
  border-bottom: 1px solid #A1B4B0;
}

#drag .title div {
  position: absolute;
  height: 19px;
  top: 2px;
  right: 0;
}

#drag .title a, a.open {
  float: left;
  width: 21px;
  height: 19px;
  display: block;
  margin-left: 5px;
  background: url(https://www.17sucai.com/preview/65612/2014-02-17/Desktop1/img/tool.png) no-repeat;
}

a.open {
  position: absolute;
  top: 10px;
  left: 50%;
  margin-left: -10px;
  background-position: 0 0;
}

a.open:hover {
  background-position: 0 -29px;
}

#drag .title a.min {
  background-position: -29px 0;
}

#drag .title a.min:hover {
  background-position: -29px -29px;
}

#drag .title a.max {
  background-position: -60px 0;
}

#drag .title a.max:hover {
  background-position: -60px -29px;
}

#drag .title a.revert {
  background-position: -149px 0;
  display: none;
}

#drag .title a.revert:hover {
  background-position: -149px -29px;
}

#drag .title a.close {
  background-position: -89px 0;
}

#drag .title a.close:hover {
  background-position: -89px -29px;
}

#drag .content {
  overflow: auto;
  margin: 0 5px;
}

#drag .resizeBR {
  position: absolute;
  width: 14px;
  height: 14px;
  right: 0;
  bottom: 0;
  overflow: hidden;
  cursor: nw-resize;
  background: url(https://www.17sucai.com/preview/65612/2014-02-17/Desktop1/img/resize.png) no-repeat;
}

#drag .resizeL, #drag .resizeT, #drag .resizeR, #drag .resizeB, #drag .resizeLT, #drag .resizeTR, #drag .resizeLB {
  position: absolute;
  background: #000;
  overflow: hidden;
  opacity: 0;
  filter: alpha(opacity=0);
}

#drag .resizeL, #drag .resizeR {
  top: 0;
  width: 5px;
  height: 100%;
  cursor: w-resize;
}

#drag .resizeR {
  right: 0;
}

#drag .resizeT, #drag .resizeB {
  width: 100%;
  height: 5px;
  cursor: n-resize;
}

#drag .resizeT {
  top: 0;
}

#drag .resizeB {
  bottom: 0;
}

#drag .resizeLT, #drag .resizeTR, #drag .resizeLB {
  width: 8px;
  height: 8px;
  background: #FF0;
}

#drag .resizeLT {
  top: 0;
  left: 0;
  cursor: nw-resize;
}

#drag .resizeTR {
  top: 0;
  right: 0;
  cursor: ne-resize;
}

#drag .resizeLB {
  left: 0;
  bottom: 0;
  cursor: ne-resize;
}
</style>
